﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geodatabase;
using System.IO;
using Esri.FileGDB;
using System.Data;

namespace FRS.EsriExtension
{
    public static class GeodatabaseExtension
    {
        /// <summary>
        /// 删除指定要素类。
        /// <para>例如:workspacePath=@"G:\doc\gis\1.400\data\pdb.mdb", featureClassPath="res2_4m".</para>
        /// </summary>
        /// <param name="gdbPath">gdb的位置</param>
        /// <param name="featureClassName">需要删除的要素的名称【不需要指定要素数据集】</param>
        /// <returns>是否删除成功</returns>
        public static bool DeleteFeatureClass(string featureClassName, string gdbPath)
        {
            if (Directory.Exists(gdbPath))
            {
                IWorkspaceFactory pTargetWorkspaceFactory = null;
                IWorkspace pTargetWorkspace = null;
                try
                {
                    // 打开gdb的工作空间
                    pTargetWorkspaceFactory = new FileGDBWorkspaceFactory();
                    pTargetWorkspace = pTargetWorkspaceFactory.OpenFromFile(gdbPath, 0);
                    IFeatureWorkspace pTargetFeatureWorkspace = pTargetWorkspace as IFeatureWorkspace;
                    IFeatureClass pFeatureClass = pTargetFeatureWorkspace.OpenFeatureClass(featureClassName);
                    // 注意的是这里需要为IDataset(IFeatureClass没有删除的功能).
                    (pFeatureClass as IDataset).Delete();
                    return true;
                }
                catch (Exception ex)
                {
                    ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("在空间数据库“{0}”中删除要素“{1}”失败", pTargetWorkspace.PathName, featureClassName));
                    return false;
                }
            }
            else
            {
                System.Windows.Forms.MessageBox.Show("GDB文件不存在", "警告", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
                ExceptionLog.ExceptionLogRecorder.WriteSelfDefineErrorLog(string.Format("空间数据库“{0}”不存在(NOT FOUND)", Path.GetFullPath(gdbPath)));
                return false;
            }
        }
        /// <summary>
        /// 将要素类导入到指定的空间数据库中的某个特定的要素数据集中【Geodatabase.FeatureDataSet】
        /// <para>@Warning: 如果需要导入至特定的要素数据集，则需要保证导入的要素类用一致的空间参考信息，否则会导入空数据！</para>
        /// <para>@Warning: 保证目标gdb中不含有导入要素类的重命名，否则将会导入失败！</para>
        /// </summary>
        /// <param name="pSourceFeatureClass">源要素类【导入哪个shp文件】</param>
        /// <param name="gdbPath">指定的空间数据库位置【导入到哪个数据库】</param>
        /// <param name="targetDatasetName">目标要素数据集的名称【导入到哪个范围】[default=导入至gdb的根目录下]</param>
        /// <param name="targetFeatureClassName">目标要素类的名称【导入时重命名】[default=以导入要素类的名字命名]</param>
        /// <param name="pQueryFilter">需要的筛选命令[default=导入全部要素]</param>
        /// <returns>如果导入成功返回TRUE，否则返回FALSE</returns>
        public static bool ImportFeatureClass(IFeatureClass pSourceFeatureClass, string gdbPath, string targetDatasetName = null, string targetFeatureClassName = null, IQueryFilter pQueryFilter = null)
        {
            #region 源数据工作空间（SHP）
            IDataset pSourceDataset = pSourceFeatureClass as IDataset;
            IFeatureClassName pSourceFeatureClassName = pSourceDataset.FullName as IFeatureClassName;
            IWorkspace pSourceWorkspace = pSourceDataset.Workspace;
            #endregion
            #region 目标数据工作空间（GDB）
            IWorkspaceFactory pTargetWorkspaceFactory = new FileGDBWorkspaceFactory();
            IWorkspace pTargetWorkspace = pTargetWorkspaceFactory.OpenFromFile(gdbPath, 0);
            IFeatureWorkspace pTargetFeatureWorkspace = pTargetWorkspace as IFeatureWorkspace;
            #endregion
            #region 若要素数据集名称不为空，则获取该数据集，默认放在Geodatabase的“根目录”下
            IFeatureDatasetName pTargetFeatureDatasetName = null;
            if (!(string.IsNullOrWhiteSpace(targetDatasetName)))
            {
                pTargetFeatureDatasetName = pTargetFeatureWorkspace.OpenFeatureDataset(targetDatasetName).FullName as IFeatureDatasetName;
            }
            #endregion
            #region 设置目标数据属性
            IDataset pTargetDataSet = pTargetWorkspace as IDataset;
            IWorkspaceName pTargetWorkspaceName = pTargetDataSet.FullName as IWorkspaceName;
            IFeatureClassName pTargetFeatureClassName = new FeatureClassName() as IFeatureClassName;
            IDatasetName pTargetDatasetName = pTargetFeatureClassName as IDatasetName;
            pTargetDatasetName.WorkspaceName = pTargetWorkspaceName;
            pTargetDatasetName.Name = (string.IsNullOrWhiteSpace(targetFeatureClassName) ? pSourceFeatureClass.AliasName : targetFeatureClassName);
            #endregion
            #region 检查字段并进行转换
            IFieldChecker pFieldChecker = new FieldChecker();
            pFieldChecker.InputWorkspace = pSourceWorkspace;
            pFieldChecker.ValidateWorkspace = pTargetWorkspace;

            IFields pSourceFields = pSourceFeatureClass.Fields;
            IFields pTargetFields = null;
            IEnumFieldError pEnumFieldError = null;
            pFieldChecker.Validate(pSourceFields, out pEnumFieldError, out pTargetFields);
            #endregion
            #region 数据转换
            IFeatureDataConverter pFeatureDataConverter = new FeatureDataConverter();
            try
            {
                pFeatureDataConverter.ConvertFeatureClass(pSourceFeatureClassName, pQueryFilter, pTargetFeatureDatasetName, pTargetFeatureClassName, null, pTargetFields, "", 1000, 0);
                return true;
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, pSourceFeatureClass.AliasName + "导入Geodatabase：" + gdbPath + "失败\n可能该数据库中含有同名要素类");
                return false;
            }
            #endregion
        }
        /// <summary>
        /// 将ESRI公司提供的RowCollection转换为Microsoft公司提供的DataTable
        /// <para>@Tips: 如果不想查询任何东西输入NULL或者""</para>
        /// </summary>
        /// <param name="geodatabase">开发人员提供空间数据库</param>
        /// <param name="tableName">表名</param>
        /// <param name="whereClause">where字句名</param>
        /// <param name="subFields">查询的子字段</param>
        /// <returns>DataTable</returns>
        public static DataTable ConvertToDataTable(this Geodatabase geodatabase, string tableName, string whereClause, params string[] subFields)
        {
            // 新建一个DataTable和子字段
            DataTable dataTable = new DataTable();
            string subFieldStatement = null;
            #region 为dataTable添加字段
            foreach (string subField in subFields)
            {
                dataTable.Columns.Add(subField);
                subFieldStatement += "," + subField;
            }
            subFieldStatement = subFieldStatement.Substring(1);
            #endregion
            #region 设置SQL语句
            Esri.FileGDB.Table table;
            try
            {
                table = geodatabase.OpenTable("\\" + tableName);
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("空间数据库“{0}”中没有找到表“{1}”", geodatabase, tableName));
                return null;
            }
            string sqlStatement = null;
            if (string.IsNullOrWhiteSpace(whereClause))
            {
                sqlStatement = string.Format("SELECT {0} FROM {1}", subFieldStatement, tableName);
            }
            else
            {
                sqlStatement = string.Format("SELECT {0} FROM {1} WHERE {2}", subFieldStatement, tableName, whereClause);
            }
            #endregion
            #region 开始执行SQL语句
            try
            {
                foreach (Esri.FileGDB.Row row in geodatabase.ExecuteSQL(sqlStatement))
                {
                    DataRow newRow = dataTable.NewRow();
                    int index = 0;
                    foreach (string subField in subFields)
                    {
                        newRow[subField] = row[subField].ToString();
                        index++;
                    }
                    dataTable.Rows.Add(newRow);
                }
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("表“{0}”中可能不包含字段“{1}”或者WHERE字句“{2}”出错", tableName, subFieldStatement, whereClause));
                return null;
            }
            #endregion

            table.Close();
            return dataTable;
        }
    }
}
